#include "wav.h"

FILE* openWAV(const char *filename, const char* mode, WAVHeader * header, unsigned length) {
    FILE * fd = NULL;
    if ((fd = fopen(filename, mode)) == NULL) {
#ifdef DEBUG
        fprintf(stderr, "file %s could not be opened.\n", filename);
#endif
        return NULL;
    }

    if ((strcmp(mode, "rb") == 0) && (header != NULL)) {
        if (getHeader(fd, &header) == 0) {
#ifdef DEBUG
            fprintf(stderr, "not valid file, the header could not be read.\n", filename);
#endif
            fclose(fd);
            return NULL;
        }
    } else if ((header != NULL) && (strcmp(mode, "w") == 0)) {
        if (putHeader(fd, header, length) != sizeof (WAVHeader)) {
#ifdef DEBUG
            fprintf(stderr, "not valid file, the header could not be written.\n", filename);
#endif
            fclose(fd);
            return NULL;
        }
    }
    return fd;
}

unsigned readWAV(FILE* fd, const unsigned length, void * where) {
    return fread(where, 1, length, (FILE*) fd);
}

unsigned saveWAV(FILE* fd, const unsigned length, void * where) {
    return fwrite(where, 1, length, fd);
}

unsigned getLength(FILE* fd) {
    unsigned length;
    fseek(fd, 0L, SEEK_END);
    length = ftell(fd) - sizeof (WAVHeader);
    fseek(fd, 0L, SEEK_SET);
    return length;
}

unsigned getHeader(FILE* fd, WAVHeader **header) {
    const unsigned size = sizeof (WAVHeader);
    unsigned len = readWAV(fd, size, (void*) *header);
    return len;
}

unsigned putHeader(FILE* fd, WAVHeader * wavHeader, unsigned length) {
    if (length != 0) {
        wavHeader->subChunk2Size = length;
    }
    return saveWAV(fd, sizeof (WAVHeader), (void*) wavHeader);
}

void closeWAV(FILE** fd) {
    FILE* file = *fd;
    fclose(file);
    *fd = NULL;
}

int saveVoice(WaveData *voice, WAVHeader *header, char *filename) {
    FILE *WAVFile;
#ifdef DEBUG
    printf("saving file...%s\n", filename);
#endif
    //If it can't be opened...
    WAVFile = fopen(filename, "w");
    if (WAVFile == NULL) {
#ifdef DEBUG
        printf("File could not be opened\n");
#endif
        return (0);
    }
    header->subChunk2Size = voice->soundLength;
#ifdef DEBUG
    printf("size: %lu\n", header->subChunk2Size);
#endif
    fwrite(header, sizeof (WAVHeader), 1, WAVFile);
    unsigned long savedSize = fwrite(voice->sample, 1, voice->soundLength, WAVFile);
#ifdef DEBUG
    printf("grabado: %lu\n", savedSize);
#endif

    return 0;
}

int loadHeader(WAVHeader * header, char * filename) {
    FILE *WAVFile;
    //int i;
    int n = 0;
    //If it can't be opened...
    WAVFile = fopen(filename, "rb");
    if (WAVFile == NULL) {
#ifdef DEBUG
        printf("File could not be opened\n");
#endif
        return (0);
    }
    //Return length of file for sound length minus 48 bytes for .WAV
    //header
    fread(header, sizeof (WAVHeader), 1, WAVFile);
    fclose(WAVFile); //Close the file
    return 0;
}

int loadSamples(WaveData *voice, char*filename) {
    FILE *WAVFile;
    int n = 0;
    //If it can't be opened...
    WAVFile = fopen(filename, "rb");
    if (WAVFile == NULL) {
#ifdef DEBUG
        printf("File could not be opened\n");
#endif
        return (0);
    }
    //Return length of file for sound length minus 48 bytes for .WAV
    //header
    fseek(WAVFile, 0L, SEEK_END);
    voice->soundLength = ftell(WAVFile);
    fseek(WAVFile, 0L, SEEK_SET);
    if (voice->sample) free(voice->sample);
    voice->sample = (char *) malloc(voice->soundLength + 1); //Assign memory
    if (!voice->sample) return (0);
    //Load the sample data
    n = fread(voice->sample, 1, voice->soundLength, WAVFile);
#ifdef DEBUG
    printf("Read: %d\n", n);
    printf("File len: %d\n", voice->soundLength);
#endif
    fclose(WAVFile); //Close the file
    return (1);
}

int loadVoice(WaveData *voice, WAVHeader * header, char *filename) {
    FILE *WAVFile;
    //int i;
    int n = 0;
    //If it can't be opened...
    WAVFile = fopen(filename, "rb");
    if (WAVFile == NULL) {
#ifdef DEBUG
        printf("File could not be opened\n");
#endif
        return (0);
    }
    //Return length of file for sound length minus 48 bytes for .WAV
    //header
    fseek(WAVFile, 0L, SEEK_END);
    voice->soundLength = ftell(WAVFile) - sizeof (WAVHeader);
    fseek(WAVFile, 0L, SEEK_SET);

    //Check RIFF header
    if (voice->sample) {
        free(voice->sample);
    }
    voice->sample = (char *) malloc(voice->soundLength); //Assign memory
    if (!voice->sample) {
        return (0);
    }

    //Load the sample data
    int read = fread(header, 1, sizeof (WAVHeader), WAVFile);
#ifdef DEBUG
    printf("header size: %d\n", read);
#endif

    //Check RIFF header
    if (*(unsigned long *) header->RIFF != 0x46464952) {
#ifdef DEBUG
        printf("Not a wave file\n");
#endif
        return (0);
    }

    //Check channels
    if (header->numOfChan != 1) {
#ifdef DEBUG
        printf("Not a mono wave file\n");
#endif
        return (0);
    }

    //Check bit resolution
    if (header->bitsPerSample != 16) {
#ifdef DEBUG
        printf("Not an 16-bit wave file");
#endif
        return (0);
    }
    voice->frequency = header->samplesPerSec;

    //Load the sample data
    n = fread(voice->sample, 1, voice->soundLength, WAVFile);
#ifdef DEBUG
    printf("load to memory: %d\n", n);
#endif

    fclose(WAVFile); //Close the file
    return (1);
}